section .text
[BITS 16]
[org 0x7E00]

_main:
    ;---------------------------------------------
    ;   Set up the segment registers and the stack    
    ;---------------------------------------------
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov sp, 0xFFFF
    
    ;-------------------------------------------------------------------
    ;   Enter protected mode. After this we can no longer use interrupts
    ;-------------------------------------------------------------------
enter_protected_mode:    

    cli ; Turn off interrupts
       
    ;----------------------------------------
	; set up data for entering protected mode
	;----------------------------------------
    	
    lgdt [GlobalDescriptorTable] ; load the GDT
    mov eax,cr0 ; eax = machine status word (MSW)
    or al,1     ; set the protection enable bit of the MSW to 1

    mov cr0,eax ; start protected mode

    ; Reload data segment registers:
    xor eax, eax
    mov ax, 0x08 ; 0x08 points at the new data selector
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
        
    ;-------------------------------
    ;   We are now in protected mode
    ;------------------------------- 
    jmp 0x10:far_jump
far_jump:
[BITS 32]


    ;--------------
    ; Load the IDT 
    ;--------------
    mov word [isr_table], generic_interrupt    
    lidt [idtr]
    call load_idt
                    
    xor eax, eax
    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx

    ;--------------------
    ; Load the executable
    ; 
    ; TODO: Right now we end up having to load the sections anyway.
    ;       The elf documentation says for executables the image will 
    ;       exist and the sections may or may not exist. But for my
    ;       compiler the sections do exist. I would almost rather load
    ;       from the sections. See the code that follows loading
    ;       the executable. Its to load missing strings... etc. We
    ;       may as well load from there.
    ;
    call load_elf_header
    call load_elf_executable

    ;----------------------------------------
    ; Gets the string section 
    ;----------------------------------------
    xor eax, eax
    xor ebx, ebx
    xor ecx, ecx
    mov ax, [ELF_SHSTRNDX]  ; load the string index
    mov bx, [ELF_SHENTSIZE] ; load the size of all individual sections
    mul bx                  ; elf_shstrndx * elf_shentsize = the index to the string section
    add ax, [ELF_SHOFF]     ; add the offset of the sections
    add eax, 0x00010000     ; add the offset of the kernel in memory
    
    mov esi, eax
    mov cx, [ELF_SHENTSIZE]
    call load_elf_section

    mov eax, [SECTION_OFFSET]    
    mov [ELF_STRING_SECTION], eax   ; store the location of the string section to elf_string_section variable
   
    ;---------------------------------------
    ; Loads the missing data section :)
    ;---------------------------------------
    xor eax, eax
    xor ebx, ebx
    xor ecx, ecx
    
    mov bx, [ELF_SHNUM]         ; the number of sections  
    mov esi, [ELF_SHOFF]        ; the first section offset
    add esi, 0x00010000         ; where in memory the kernel is loaded
    mov cx, [ELF_SHENTSIZE]     ; size of the sections

    load_elf_sections_start:    

        push eax
        push ebx
        push ecx
        push esi

        call load_elf_section
        
        ;--------------------------------------------------------------------
        ; Loads the location of the section name then compares it to .rodata. 
        ;--------------------------------------------------------------------
        mov eax, [ELF_STRING_SECTION]
        add eax, [SECTION_NAME]
        add eax, 0x00010000
        mov esi, eax
        mov ebx, szRODATA 
        call strcmp       
        
        cmp ax, 0x01
        je set_up_rodata
        mov ax, 0x0000
        mov [reg32], ax
        call printreg32
        jmp set_up_rodata_end
         
set_up_rodata:  ; this should load the .rodata section
        mov eax, [ELF_STRING_SECTION]
        add eax, [SECTION_NAME]
        add eax, 0x00010000
        mov esi, eax
        call sprint
          
        mov ax, 0x0001        
        mov [reg32], ax
        call printreg32

        mov edi, [SECTION_ADDR]
        mov esi, 0x00010000
        add esi, [SECTION_OFFSET]
        mov ecx, [SECTION_SIZE]
        rep movsb
        
set_up_rodata_end:
                        
        pop esi
        pop ecx
        pop ebx
        pop eax
        
        add eax, 1
        add esi, ecx

        cmp eax, ebx
        jl load_elf_sections_start        
        
    load_elf_sections_end:
    
    ;-------------------------------------
    ; Sets up the long jump to the kernel
    ;-------------------------------------
    
    xor eax, eax
    mov ax, 0x08 ; 0x10 points at the new data selector
    mov ds, ax
    mov es, ax
    mov fs, ax
    
    mov eax, isr_table
    mov [reg32], eax
    call printreg32
    
    mov eax, isr_table

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; Elf entry contains the address to jump to once the elf executable has been loaded
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    mov ebx, [ELF_ENTRY]    
    jmp ebx
    
loop_forever:
    jmp loop_forever

_main_end:    


;=========================
; string compare
; esi - string to compare
; ebx - string to compare to
;
; return value in eax - 0 if not equal, 1 if equal
;=========================
strcmp:
    push esi
    push ebx
    
    strcmp_iterate_start:
        xor eax, eax
        mov al, [esi]
        mov ah, [ebx]
        
        cmp al, 0x00
        je strcmp_iterate_end
        
        cmp ah, 0x00
        je strcmp_iterate_end
        
        inc esi
        inc ebx
        cmp al, ah
        je strcmp_iterate_start
        jmp strcmp_not_equal
    strcmp_iterate_end:    
 
        cmp al, ah
        jne strcmp_not_equal
    
    strcmp_equal:
        mov eax, 0x01   ; return true
        jmp strcmp_exit 
           
    strcmp_not_equal:
        mov eax, 0x00   ; return false
            
    strcmp_exit:
    
        pop ebx
        pop esi

        ret

         
;=======================================
; Print String
;
; esi - null terminated string
; edi - the location of video memory
;
;=======================================
print_string:           

    push ax
    
print_string_start:
    
    mov al, byte [esi]
    cmp al, 0x00
    je print_string_end
    
    mov ah, 0x00
    call print_char
    
    inc esi
    add edi, 2 ; 2 bytes because every other byte is the color
    
    jmp print_string_start
     
print_string_end:
    
    pop ax

    ret

;=========================================================
; Print Char
;
; ah     - The color to print   0x00 (white) - 0xFF (black)
; al     - The character to print
; fs:edi - The screen location to print to
;
;=========================================================
print_char:

    mov [fs:edi],al	; write char to display memory
    ret


;----------------------
dochar:
    call cprint              ; print one character
sprint:
    mov eax, [esi]          ; string char to AL
    lea esi, [esi+1]
    cmp al, 0
    jne dochar               ; else, we're done
    add byte [ypos], 1       ; down one row
    mov byte [xpos], 0       ; back to left
    ret
 
cprint:
    mov ah, 0xF0             ; attrib = white on black
    mov ecx, eax             ; save char/attribute
    movzx eax, byte [ypos]
    mov edx, 160             ; 2 bytes (char/attrib)
    mul edx                  ; for 80 columns
    movzx ebx, byte [xpos]
    shl ebx, 1               ; times 2 to skip attrib
 
    mov edi, 0xb8000         ; start of video memory
    add edi, eax             ; add y offset
    add edi, ebx             ; add x offset
 
    mov eax, ecx             ; restore char/attribute
    mov word [ds:edi], ax
    add byte [xpos], 1       ; advance to right
 
    ret
 
;------------------------------------

printreg32:
    mov edi, outstr32
    mov eax, [reg32]
    mov esi, hexstr
    mov ecx, 8               ; eight nibbles
 
hexloop:
    rol eax, 4               ; leftmost will
    mov ebx, eax             ; become rightmost
    and ebx, 0x0f ;
    mov bl, [esi + ebx]      ; index into hexstr
    mov [edi], bl
    inc edi
    dec ecx
    jnz hexloop
 
    mov esi, outstr32
    call sprint
 
    ret
 
;------------------------------------
 
xpos db 0
ypos db 0
hexstr db '0123456789ABCDEF'
outstr32 db '00000000', 0    ; register value
reg32 dd 0                   ; pass values to printreg32
 
;------------------------------------


elf_header:

    ELF_IDENT       db  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ELF_RESERVED    db  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    ELF_TYPE        dw  0x0000      ;
    ELF_MACHINE     dw  0x0000      ;
    ELF_VERSION     dd  0x00000000  ;
    ELF_ENTRY       dd  0x00000000  ; Entry point for executing code
    ELF_PHOFF       dd  0x00000000  ; program header offset (executable)
    ELF_SHOFF       dd  0x00000000  ; section header offset (initialized data, executable, etc)
    ELF_FLAGS       dd  0x00000000  ;
    ELF_EHSIZE      dw  0x0000      ; size of the elf header
    ELF_PHENTSIZE   dw  0x0000      ; program header size
    ELF_PHNUM       dw  0x0000      ; number of program headers
    ELF_SHENTSIZE   dw  0x0000      ; section header size
    ELF_SHNUM       dw  0x0000      ; number of section headers
    ELF_SHSTRNDX    dw  0x0000      ; String index section header number
    
load_elf_header:
    push esi
    push edi
    push ecx

    mov esi, 0x00010000       
    mov edi, elf_header
    mov ecx, 0x34 ; elf header size in bytes
    rep movsb

    pop ecx
    pop edi
    pop esi

    retn

elf_program_header:
    P_TYPE      dd  0x00000000 ; 32word
    P_OFFSET    dd  0x00000000 ; 32offset
    P_VADDR     dd  0x00000000 ; 32addr
    P_PADDR     dd  0x00000000 ; 32addr
    P_FILESZ    dd  0x00000000 ; 32addr
    P_MEMSZ     dd  0x00000000 ; 32word
    P_FLAGS     dd  0x00000000 ; 32word
    P_ALIGN     dd  0x00000000 ; 32word

load_elf_program_header:

    push esi
    push edi
    push ecx

    ; esi contains the start of the section       
    mov edi, elf_program_header
    mov ecx, ebx; ebx contains elf header size in bytes
    rep movsb

    pop ecx
    pop edi
    pop esi

    retn


; section data structure
elf_section:
    SECTION_NAME dd 0x00000000
    SECTION_TYPE dd 0x00000000
    SECTION_FLAGS dd 0x00000000
    SECTION_ADDR dd 0x00000000
    SECTION_OFFSET dd 0x00000000
    SECTION_SIZE dd 0x00000000
    SECTION_LINK dd 0x00000000
    SECTION_INFO dd 0x00000000
    SECTION_ADDRALIGN dd 0x00000000
    SECTION_ENTSIZE dd 0x00000000

; esi contains the start of the section       
; ecx contains elf header size in bytes
load_elf_section:

    push esi
    push edi
    push ecx

    ; esi contains the start of the section       
    mov edi, elf_section
    ; ecx contains elf header size in bytes
    rep movsb

    pop ecx
    pop edi
    pop esi

    retn

;;;;;;;

load_elf_executable:    
    
    call load_elf_header
      
    mov esi, [ELF_PHOFF] ; Offset from the start of the file at 64K
    add esi, 0x00010000 ; where the file is loaded, 64K 
    mov ax, 0x0000
    xor ecx, ecx
    mov cx, [ELF_PHNUM]
    xor ebx, ebx
    mov bx, [ELF_PHENTSIZE]
        
load_elf_executable_loop_start:
    push eax
    push ebx
    push ecx
    push esi
    
    call load_elf_program_header    
    
    mov eax, [P_PADDR]          ; eax contains the address the program belongs at

    cmp eax, 0x00000000
    je skip_loading

    mov edi, eax                ; Contains p_addr, where to load the memory to

    mov ebx, [P_OFFSET]         ; offset in kernel loading segment is in ebx
    mov esi, 0x00010000         ; Base address of the memory to load from
    add esi, ebx                ; offset in the file to load from
    
    mov ecx, [P_FILESZ]         ; size of stuff to load is in ecx (bytes)
    rep movsb                   ;supposedly we have just moved a piece of the executable its expected address
    
    mov eax, [P_PADDR]
    mov ebx, [P_FILESZ]
    add eax, ebx
    ;mov dword [reg32], eax
    ;call printreg32
            
    
skip_loading:
    pop esi
    pop ecx
    pop ebx
    pop eax
    
    add si, bx
    inc ax
    cmp ax, cx
    jl load_elf_executable_loop_start        
            
    retn


;--------------------------
; generic interrupt handler
;--------------------------

generic_interrupt:
    
    ; move esp like c functions do?
        
    mov ebx, esp
    mov eax, [ebx + 4] 
    mov [reg32], eax
    call printreg32
 
    mov ebx, esp    
    mov eax, [ebx + 8]
    mov [reg32], eax
    call printreg32
    
    ret    
;--------------------------
; ISR handler.
;--------------------------
isr_handler:

    ; This is lame... save eax without pushing it
    mov [interrupt_eax], eax
    
    ; Save the interrupt number
    xor eax, eax
    pop eax
    mov [interrupt_num], eax
    
    ; save the interrupt error
    pop eax
    mov [interrupt_error], eax
    mov eax, [interrupt_eax]    

    pusha
    push ds
    push es
    push fs
    push gs
    mov ax, 0x08   ; Load the Kernel Data Segment descriptor!
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
        
    mov eax, [interrupt_num]
    push eax

    mov eax, [interrupt_error]
    push eax

    ; Call whatever method we are pointed to by the isr_table... it's not really a table
    mov eax, [isr_table]
    call eax       ; A special call, preserves the 'eip' register
    pop eax
    pop eax 
    pop gs
    pop fs
    pop es
    pop ds
    popa
    iret           ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP!

;--------------------------
; mapped interrupt handler
;--------------------------

%macro ISR 1
[GLOBAL isr%1]
isr%1:
    cli
    push 0
    push %1
    jmp isr_handler
         
%endmacro

%macro ISR_ERROR 1
[GLOBAL isr%1]
isr%1:
    cli
    push %1
    jmp isr_handler
         
%endmacro

ISR 0
ISR 1
ISR 2
ISR 3
ISR 4
ISR 5
ISR 6
ISR 7
ISR_ERROR 8
ISR 9
ISR_ERROR 10
ISR_ERROR 11
ISR_ERROR 12
ISR_ERROR 13
ISR_ERROR 14
ISR 15
ISR 16
ISR_ERROR 17
ISR 18
ISR 19
ISR 20
ISR 21
ISR 22
ISR 23
ISR 24
ISR 25
ISR 26
ISR 27
ISR 28
ISR 29
ISR 30
ISR 31
ISR 32
ISR 33
ISR 34
ISR 35
ISR 36
ISR 37
ISR 38
ISR 39
ISR 40
ISR 41
ISR 42
ISR 43
ISR 44
ISR 45
ISR 46
ISR 47
ISR 48
ISR 49
ISR 50
ISR 51
ISR 52
ISR 53
ISR 54
ISR 55
ISR 56
ISR 57
ISR 58
ISR 59
ISR 60
ISR 61
ISR 62
ISR 63
ISR 64
ISR 65
ISR 66
ISR 67
ISR 68
ISR 69
ISR 70
ISR 71
ISR 72
ISR 73
ISR 74
ISR 75
ISR 76
ISR 77
ISR 78
ISR 79
ISR 80
ISR 81
ISR 82
ISR 83
ISR 84
ISR 85
ISR 86
ISR 87
ISR 88
ISR 89
ISR 90
ISR 91
ISR 92
ISR 93
ISR 94
ISR 95
ISR 96
ISR 97
ISR 98
ISR 99
ISR 100
ISR 101
ISR 102
ISR 103
ISR 104
ISR 105
ISR 106
ISR 107
ISR 108
ISR 109
ISR 110
ISR 111
ISR 112
ISR 113
ISR 114
ISR 115
ISR 116
ISR 117
ISR 118
ISR 119
ISR 120
ISR 121
ISR 122
ISR 123
ISR 124
ISR 125
ISR 126
ISR 127
ISR 128
ISR 129
ISR 130
ISR 131
ISR 132
ISR 133
ISR 134
ISR 135
ISR 136
ISR 137
ISR 138
ISR 139
ISR 140
ISR 141
ISR 142
ISR 143
ISR 144
ISR 145
ISR 146
ISR 147
ISR 148
ISR 149
ISR 150
ISR 151
ISR 152
ISR 153
ISR 154
ISR 155
ISR 156
ISR 157
ISR 158
ISR 159
ISR 160
ISR 161
ISR 162
ISR 163
ISR 164
ISR 165
ISR 166
ISR 167
ISR 168
ISR 169
ISR 170
ISR 171
ISR 172
ISR 173
ISR 174
ISR 175
ISR 176
ISR 177
ISR 178
ISR 179
ISR 180
ISR 181
ISR 182
ISR 183
ISR 184
ISR 185
ISR 186
ISR 187
ISR 188
ISR 189
ISR 190
ISR 191
ISR 192
ISR 193
ISR 194
ISR 195
ISR 196
ISR 197
ISR 198
ISR 199
ISR 200
ISR 201
ISR 202
ISR 203
ISR 204
ISR 205
ISR 206
ISR 207
ISR 208
ISR 209
ISR 210
ISR 211
ISR 212
ISR 213
ISR 214
ISR 215
ISR 216
ISR 217
ISR 218
ISR 219
ISR 220
ISR 221
ISR 222
ISR 223
ISR 224
ISR 225
ISR 226
ISR 227
ISR 228
ISR 229
ISR 230
ISR 231
ISR 232
ISR 233
ISR 234
ISR 235
ISR 236
ISR 237
ISR 238
ISR 239
ISR 240
ISR 241
ISR 242
ISR 243
ISR 244
ISR 245
ISR 246
ISR 247
ISR 248
ISR 249
ISR 250
ISR 251
ISR 252
ISR 253
ISR 254
ISR 255

isr_lookup:
    dd isr0
    dd isr1
    dd isr2
    dd isr3
    dd isr4
    dd isr5
    dd isr6
    dd isr7
    dd isr8
    dd isr9
    dd isr10
    dd isr11
    dd isr12
    dd isr13
    dd isr14
    dd isr15
    dd isr16
    dd isr17
    dd isr18
    dd isr19
    dd isr20
    dd isr21
    dd isr22
    dd isr23
    dd isr24
    dd isr25
    dd isr26
    dd isr27
    dd isr28
    dd isr29
    dd isr30
    dd isr31
    dd isr32
    dd isr33
    dd isr34
    dd isr35
    dd isr36
    dd isr37
    dd isr38
    dd isr39
    dd isr40
    dd isr41
    dd isr42
    dd isr43
    dd isr44
    dd isr45
    dd isr46
    dd isr47
    dd isr48
    dd isr49
    dd isr50
    dd isr51
    dd isr52
    dd isr53
    dd isr54
    dd isr55
    dd isr56
    dd isr57
    dd isr58
    dd isr59
    dd isr60
    dd isr61
    dd isr62
    dd isr63
    dd isr64
    dd isr65
    dd isr66
    dd isr67
    dd isr68
    dd isr69
    dd isr70
    dd isr71
    dd isr72
    dd isr73
    dd isr74
    dd isr75
    dd isr76
    dd isr77
    dd isr78
    dd isr79
    dd isr80
    dd isr81
    dd isr82
    dd isr83
    dd isr84
    dd isr85
    dd isr86
    dd isr87
    dd isr88
    dd isr89
    dd isr90
    dd isr91
    dd isr92
    dd isr93
    dd isr94
    dd isr95
    dd isr96
    dd isr97
    dd isr98
    dd isr99
    dd isr100
    dd isr101
    dd isr102
    dd isr103
    dd isr104
    dd isr105
    dd isr106
    dd isr107
    dd isr108
    dd isr109
    dd isr110
    dd isr111
    dd isr112
    dd isr113
    dd isr114
    dd isr115
    dd isr116
    dd isr117
    dd isr118
    dd isr119
    dd isr120
    dd isr121
    dd isr122
    dd isr123
    dd isr124
    dd isr125
    dd isr126
    dd isr127
    dd isr128
    dd isr129
    dd isr130
    dd isr131
    dd isr132
    dd isr133
    dd isr134
    dd isr135
    dd isr136
    dd isr137
    dd isr138
    dd isr139
    dd isr140
    dd isr141
    dd isr142
    dd isr143
    dd isr144
    dd isr145
    dd isr146
    dd isr147
    dd isr148
    dd isr149
    dd isr150
    dd isr151
    dd isr152
    dd isr153
    dd isr154
    dd isr155
    dd isr156
    dd isr157
    dd isr158
    dd isr159
    dd isr160
    dd isr161
    dd isr162
    dd isr163
    dd isr164
    dd isr165
    dd isr166
    dd isr167
    dd isr168
    dd isr169
    dd isr170
    dd isr171
    dd isr172
    dd isr173
    dd isr174
    dd isr175
    dd isr176
    dd isr177
    dd isr178
    dd isr179
    dd isr180
    dd isr181
    dd isr182
    dd isr183
    dd isr184
    dd isr185
    dd isr186
    dd isr187
    dd isr188
    dd isr189
    dd isr190
    dd isr191
    dd isr192
    dd isr193
    dd isr194
    dd isr195
    dd isr196
    dd isr197
    dd isr198
    dd isr199
    dd isr200
    dd isr201
    dd isr202
    dd isr203
    dd isr204
    dd isr205
    dd isr206
    dd isr207
    dd isr208
    dd isr209
    dd isr210
    dd isr211
    dd isr212
    dd isr213
    dd isr214
    dd isr215
    dd isr216
    dd isr217
    dd isr218
    dd isr219
    dd isr220
    dd isr221
    dd isr222
    dd isr223
    dd isr224
    dd isr225
    dd isr226
    dd isr227
    dd isr228
    dd isr229
    dd isr230
    dd isr231
    dd isr232
    dd isr233
    dd isr234
    dd isr235
    dd isr236
    dd isr237
    dd isr238
    dd isr239
    dd isr240
    dd isr241
    dd isr242
    dd isr243
    dd isr244
    dd isr245
    dd isr246
    dd isr247
    dd isr248
    dd isr249
    dd isr250
    dd isr251
    dd isr252
    dd isr253
    dd isr254
    dd isr255

;-------------------------------------------------
; Loads the idt information one for each interupt
;-------------------------------------------------

load_idt:

    xor eax, eax
    mov ecx, idt_end - idt
    xor edx, edx   
   
    load_idt_for_loop:

        mov ebx, [isr_lookup + edx]

        mov word [idt + eax + 0], bx
        mov word [idt + eax + 2], 0000000000010000b
        mov word [idt + eax + 4], 1000111000000000b
        shr ebx, 16
        mov word [idt + eax + 6], bx 
        
        add edx, 4 
        add eax, 8
        
        cmp eax, ecx
        jl load_idt_for_loop
    
    ret

idtr:
    dw  idt_end - idt - 1
    dd  idt

section .bss

; ----------------------------
; Reserved memory for the IDT
;-----------------------------
idt: 
    resb 256*8
idt_end:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .data    

;variables
    ELF_STRING_SECTION dd 0x00000000
    RO_DATA dd 0x00000000

;data
    MSG_TOO db 'You have reached the second stage...',0

    ;MSG db 'Welcome to the OS of D00m!',0x0A,0x0D,0
    MSG_SECOND db 'You have loaded the second stage!', 0x0A, 0x0D, 0
    ERROR_RESET_MSG db 'Error reseting HD', 0x0A, 0x0D, 0
    ERROR_LOADING_STAGE db 'Error loading stage from HD', 0x0A, 0x0D, 0
    ERROR_LOADING_KERNEL db 'Error loading kernel', 0x0A, 0x0D, 0
    ENABLE_A20 db 'Enabling A20...', 0x0A, 0x0D,0
    A20_NOT_ENABLED db 'A20 is not enabled', 0x0A, 0x0D, 0
    A20_ENABLED db 'A20 is enabled', 0x0A, 0x0D, 0
    LOADING_KERNEL db 'Loading Kernel...', 0x0A, 0x0D, 0
    HEX db '0123456789ABCDEF', 0
    HEX_FAIL db 'create_HEX_BYTE_STR must have an ax value >= 0 and < 16', 0x0A, 0x0D, 0
    ZERO_CHAR db '0'
    ZERO db '0', 0
    ONE db '1', 0
    CRLF db 0x0A, 0x0D, 0
    SPACE db ' ', 0
    
    szSECTION_TYPE db 'Section Type: ', 0x00
    szRODATA db '.rodata', 0x00  
    
    szIntOff db 'Turning Interrupts Off', 0
    szIntOn  db 'Turning Interrupts On', 0    
    szAllDone db 'All done!', 0
    
    isr_table dd 0x0000000000000000
        
    interrupt_eax dd 0
    interrupt_error dd 0
    interrupt_num dd 0
        
GlobalDescriptorTable:   

	; the global descriptor table is the heart of protected mode
	; entries are used to map virtual to physical memory
	; among other things
	;
	; each descriptor contains 8 bytes, "organized" as follows:
	;
	; |----------------------2 bytes--------------------|
	;
	; +-------------------------------------------------+
	; | segment address 24-31  | flags #2  | len 16-19  | +6
	; +-------------------------------------------------+
	; | flags #1               | segment address 16-23  | +4
	; +-------------------------------------------------+
	; | segment address bits 0-15                       | +2
	; +-------------------------------------------------+
	; | segment length bits 0-15                        | +0
	; +-------------------------------------------------+

	; the high-order bit of flags #2 controls "granularity"
	; setting it to 1 multiplies the segment length by 4096

	;======================================================

	; create two descriptors:
	; one for the GDT itself, plus a 4 gibabyte data segment

	dw GlobalDescriptorTableEnd - GlobalDescriptorTable - 1
	; segment address bits 0-15, 16-23
	dw GlobalDescriptorTable
	db 0
	; flags 1, segment length 16-19 + flags 2
	db 0, 0
	; segment address bits 24-31
	db 0 

    ; a data segment
	;
    dw 0xFFFF 	; segment length 0-15
	db 0, 0, 0 	; segment address 0-15, 16-23 
	db 0x93 	; flags 1
	db 0xCF 	; flags 2, segment length 16-19
	db 0		; segment address 24-31

	; a code segment
	;
    dw 0xFFFF 	    ; segment length 0-15
	db 0, 0, 0 	    ; segment address 0-15, 16-23
	db 10011010b 	; flags 1
	db 11001111b 	; flags 2, segment length 16-19
	db 0		    ; segment address 24-31

	 
GlobalDescriptorTableEnd:

;===========================================   

;TIMES 5118 - ($ - $$) db 0
DW 0xAA55

